﻿using Microsoft.AspNetCore.Authorization;
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Authorization;
using Volo.Abp.Users;
using System.Collections.Generic;
using Microsoft.Extensions.Localization;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using System.Security;
using Volo.Abp.PermissionManagement;
using Microsoft.EntityFrameworkCore;

namespace EcoSystem
{
    /// <summary>
    /// 全局配置数据
    /// </summary>
    public class ConfigurationAppService : ApplicationService, IConfigurationAppService
    {
        private readonly IPermissionDefinitionManager _permissionDefinitionManager;
        private readonly IAuthorizationService _authorizationService;
        private readonly ISystemMenuAppService _menuAppService;
        private readonly ISystemUserAppService _userAppService;
        private readonly IDictionaryAppService _dictionaryService;
        private readonly IOrganizationAppService _organizationService;
        public IRepository<PermissionGrant, Guid> PermissionGrantRepository { set; get; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="permissionDefinitionManager"></param>
        /// <param name="authorizationService"></param>
        /// <param name="mnuAppService"></param>
        /// <param name="userAppService"></param>
        /// <param name="dictionaryService"></param>
        public ConfigurationAppService(
            IPermissionDefinitionManager permissionDefinitionManager,
            IAuthorizationService authorizationService,
            ISystemMenuAppService mnuAppService,
            ISystemUserAppService userAppService,
            IDictionaryAppService dictionaryService,
            IOrganizationAppService organizationService)
        {
            _permissionDefinitionManager = permissionDefinitionManager;
            _authorizationService = authorizationService;
            _menuAppService = mnuAppService;
            _userAppService = userAppService;
            _dictionaryService = dictionaryService;
            _organizationService = organizationService;
        }

        /// <summary>
        /// 获取当前登录用户的全局配置数据信息
        /// </summary>
        /// <returns></returns>
        public async Task<AppConfigurationDto> GetApplicationConfigurationAsync()
        {
            var authInfo = await GetAuthConfigAsync();
            var currentUser = await _userAppService.GetAsync(CurrentUser.GetId());
            var dictionarys = await _dictionaryService.GetAllListAsync(new GetDictionaryItemInput() { Status = true });
            var menuItems = await _menuAppService.GetAllListAsync(new GetSystemMenuInput() { Status = true });
            var userDepartments = await _organizationService.GetUserDepartmentsAsync(CurrentUser.GetId());
            return new AppConfigurationDto()
            {
                Auth = authInfo,
                CurrentUser = currentUser,
                CurrentDepartments = userDepartments,
                DictionaryItems = dictionarys.Select(x => new DictionaryDto()
                {
                    Code = x.Code,
                    Name = x.Name,
                    ModuleCode = x.ModuleCode,
                    Items = x.Items.OrderBy(x => x.SortIndex).ThenBy(x => x.Id)
                    .Select(x2 => new DictionaryFieldDto()
                    {
                        Name = x2.Name,
                        Value = x2.Value,
                        Description = x2.Description,
                        ExtraProperties = x2.ExtraProperties
                    }).ToList()
                }).ToList(),
                MenuItems = menuItems
            };
        }

        public List<PermissionDefinitionDto> GetPermissionDefinitionDtos(IReadOnlyList<PermissionDefinition> items)
        {
            return items.Select(x =>
            {
                var result = new PermissionDefinitionDto()
                {
                    Name = x.Name,
                    DisplayName = x.DisplayName.Localize(this.StringLocalizerFactory),
                    Properties = x.Properties
                };
                if (x.Children != null && x.Children.Count > 0)
                {
                    result.Children = GetPermissionDefinitionDtos(x.Children);
                }
                return result;
            }

            ).ToList();
        }

        public async Task<List<PermissionDefinitionDto>> GetPermissionDefinitionsAsync()
        {
            var groups = await _permissionDefinitionManager.GetGroupsAsync();
            return groups.Select(x => new PermissionDefinitionDto()
            {
                Name = x.Name,
                Properties = x.Properties,
                DisplayName = x.DisplayName.Localize(StringLocalizerFactory),
                Children = GetPermissionDefinitionDtos(x.Permissions)
            }).ToList();
        }


        /// <summary>
        /// 读取权限配置
        /// </summary>
        /// <returns></returns>
        private async Task<AppAuthConfigurationDto> GetAuthConfigAsync()
        {
            AppAuthConfigurationDto authConfig = new AppAuthConfigurationDto();
            var roleNames = CurrentUser.Roles ?? new string[] { };
            var query = (await PermissionGrantRepository.GetQueryableAsync()).AsNoTracking();
            query = query.Where(x =>
                 (roleNames.Length == 0 || (x.ProviderName == "R" && roleNames.Contains(x.ProviderKey))) ||
                (x.ProviderName == "U" && x.ProviderKey == CurrentUser.Id.ToString()));

            var names = await query.Select(x => x.Name).Distinct().ToListAsync();
            authConfig.GrantedPolicies = names.ToDictionary(x => x, x => true);
            return authConfig;
        }

        public async Task<List<DictionaryDto>> GetDictionaryAsync()
        {
            var dictionarys = await _dictionaryService.GetAllListAsync(new GetDictionaryItemInput() { Status = true });
            return dictionarys.Select(x => new DictionaryDto()
            {
                Code = x.Code,
                Name = x.Name,
                ModuleCode = x.ModuleCode,
                Items = x.Items.OrderBy(x => x.SortIndex).ThenBy(x => x.Id)
                     .Select(x2 => new DictionaryFieldDto()
                     {
                         Name = x2.Name,
                         Value = x2.Value,
                         Description = x2.Description,
                         ExtraProperties = x2.ExtraProperties
                     }).ToList()
            }).ToList();
        }

        public async Task<List<SystemMenuDto>> GetMenusAsync()
        {
            return await _menuAppService.GetAllListAsync(new GetSystemMenuInput() { Status = true });
        }
    }
}
